package com.wf.service;

import com.alibaba.fastjson.JSON;
import com.wf.dao.ESPojo.ESArticle;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class ArticleEsService {

    @Resource
    private RestHighLevelClient restHighLevelClient;
    private static final String INDEX_NAME = "article_index"; // 索引名

    // ik 分词器 - 多字段检索与高亮
    public List<ESArticle> searchByKeyword(String keyword) throws IOException {
        SearchRequest request = new SearchRequest(INDEX_NAME);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 构建多字段检索的布尔查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 在多个字段中进行匹配查询
        boolQuery.should(QueryBuilders.matchQuery("title", keyword).analyzer("ik_max_word"));
        boolQuery.should(QueryBuilders.matchQuery("content", keyword).analyzer("ik_max_word"));
        boolQuery.should(QueryBuilders.matchQuery("author", keyword).analyzer("ik_max_word"));
        boolQuery.should(QueryBuilders.matchQuery("summary", keyword).analyzer("ik_max_word"));

        // 对于viewCount这种数值类型字段，使用term查询进行精确匹配
//        try {
//            Integer viewCount = Integer.parseInt(keyword);
//            boolQuery.should(QueryBuilders.termQuery("viewCount", viewCount));
//        } catch (NumberFormatException e) {
//            // 如果关键词不是数字，忽略viewCount查询条件
//        }

        sourceBuilder.query(boolQuery);

        // 添加高亮配置（所有检索字段都需要高亮）
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title")
                .preTags("<span class=\"highlight\">")
                .postTags("</span>");
        highlightBuilder.field("content")
                .preTags("<span class=\"highlight\">")
                .postTags("</span>");
        highlightBuilder.field("author")
                .preTags("<span class=\"highlight\">")
                .postTags("</span>");
        highlightBuilder.field("summary")
                .preTags("<span class=\"highlight\">")
                .postTags("</span>");
        // 数值类型字段不需要高亮
        sourceBuilder.highlighter(highlightBuilder);

        request.source(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

        log.info("查询到的数据:"+response);

        // 解析结果（包含高亮片段）
        List<ESArticle> result = new ArrayList<>();
        for (SearchHit hit : response.getHits().getHits()) {
            ESArticle article = JSON.parseObject(hit.getSourceAsString(), ESArticle.class);

            // 处理高亮片段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();

            if (highlightFields.containsKey("title")) {
                article.setTitle(highlightFields.get("title").getFragments()[0].string());
            }

            if (highlightFields.containsKey("content")) {
                StringBuilder content = new StringBuilder();
                for (Text fragment : highlightFields.get("content").getFragments()) {
                    content.append(fragment.string());
                }
                article.setContent(content.toString());
            }

            if (highlightFields.containsKey("author")) {
                article.setAuthor(highlightFields.get("author").getFragments()[0].string());
            }

            if (highlightFields.containsKey("summary")) {
                article.setSummary(highlightFields.get("summary").getFragments()[0].string());
            }
            log.info("封装一个article:"+article);
            result.add(article);
        }
        return result;
    }

    // 创建索引（含 IK 分词配置）
    public boolean createIndex() throws IOException {
        CreateIndexRequest request = new CreateIndexRequest(INDEX_NAME);

        // 配置 mapping（指定 IK 分词）
        XContentBuilder mapping = XContentFactory.jsonBuilder()
            .startObject()
                .startObject("properties")
                    // title 字段：索引用 ik_max_word，搜索用 ik_smart
                    .startObject("title")
                        .field("type", "text")
                        .field("analyzer", "ik_max_word")
                        .field("search_analyzer", "ik_smart")
                    .endObject()
                    // content 字段：同上
                    .startObject("content")
                        .field("type", "text")
                        .field("analyzer", "ik_max_word")
                        .field("search_analyzer", "ik_smart")
                    .endObject()
                    // summary 概述字段
                    .startObject("content")
                        .field("type", "text")
                        .field("analyzer", "ik_max_word")
                        .field("search_analyzer", "ik_smart")
                    .endObject()
                    // author
                    .startObject("author")
                        .field("type","text")
                        .field("analyzer","ik_max_word")
                        .field("search_analyzer","ik_smart")
                    .endObject()
                    // createTime 字段
                    .startObject("createTime")
                        .field("type", "long")
                    .endObject()
                    .startObject("articleId")
                        .field("type","Integer")
                    .endObject()
                .endObject()
            .endObject();
        request.mapping(String.valueOf(mapping));

        String mappingStr = mapping.toString();
        System.out.println("构建的 mapping: " + mappingStr);

        // 执行创建
        CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
        return response.isAcknowledged();
    }

    // 判断索引是否存在
    public boolean existsIndex() throws IOException {
        IndicesExistsRequest request = new IndicesExistsRequest(INDEX_NAME);
//        return restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
        return true;
    }

    // 删除索引
    public boolean deleteIndex() throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest(INDEX_NAME);
        return restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT).isAcknowledged();
    }

    // 新增文档
    public String addDocument(ESArticle article) throws IOException {
        IndexRequest request = new IndexRequest(INDEX_NAME)
                .id(article.getId()) // 自定义 ID，若不填则 ES 自动生成
                .source(JSON.toJSONString(article), XContentType.JSON);

        IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
        return response.getId(); // 返回 ES 生成的 ID（若自定义则和入参一致）
    }

    // 修改文档（根据 ID 更新）
    public boolean updateDocument(ESArticle article) throws IOException {
        UpdateRequest request = new UpdateRequest(INDEX_NAME, article.getId())
                .doc(JSON.toJSONString(article), XContentType.JSON);

        UpdateResponse response = restHighLevelClient.update(request, RequestOptions.DEFAULT);
        return response.getResult() != null;
    }

    // 删除文档（根据 ID 删除）
    public boolean deleteDocument(String docId) throws IOException {
        DeleteRequest request = new DeleteRequest(INDEX_NAME, docId);
        DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
        return response.getResult() != null;
    }

    // 查询文档（根据 ID 查询）
    public ESArticle getDocument(String docId) throws IOException {
        GetRequest request = new GetRequest(INDEX_NAME, docId);
        GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
        if (response.isExists()) {
            return JSON.parseObject(response.getSourceAsString(), ESArticle.class);
        }
        return null;
    }
}